#ifndef NETCLIENT_H
#define NETCLIENT_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QWebSocket>
#include <QProtobufSerializer>
#include <QNetworkReply>

namespace model {
    class DataCenter;
    enum MessageType;
    class Message;
    class UserInfo;
    class ChatSessionInfo;
}

namespace im_proto {
    class GetUserInfoRsp;
    class GetFriendListRsp;
    class GetChatSessionListRsp;
    class GetPendingFriendEventListRsp;
    class GetRecentMsgRsp;
    class NotifyMessage;
}

namespace network {

class NetClient : public QObject
{
    Q_OBJECT
    const QString HTTP_URL = "http://127.0.0.1:8000";
    const QString WEBSOCKET_URL = "ws://127.0.0.1:8001/ws";

/* ===========================================
 *              Http 接口声明
 * ========================================== */
public:
    explicit NetClient(model::DataCenter* dataCenter);

    void ping();

    void getSelfInfo(const QString& loginSessionId);

    void getFriendList(const QString& loginSessionId);

    void getChatSessionList(const QString& loginSessionId);

    void getApplyList(const QString& loginSessionId);

    void getRecentMessageList(const QString& loginSessionId, const QString& chatSessionId);

    void sendMessage(const QString& loginSessionId, const QString& chatSessionId,
                     model::MessageType messageType, const QByteArray& content, const QString& extraInfo);

    void changeNicknameAsync(const QString& loginSessionId, const QString& nickname);

    void changeDescriptionAsync(const QString& loginSessionId, const QString& description);

    void changePhone(const QString& loginSessionId, const QString& phone, const QString& verifyCodeId, const QString& verifyCode);
    void getVerifyCode(const QString& phone);

    void changeAvatar(const QString& loginSessionId, const QByteArray& imageBytes);

    void deleteFriend(const QString& loginSessionId, const QString& userId);

    void addFriendApply(const QString& loginSessionId, const QString& userId);

    void friendApplyProcess(const QString& loginSessionId, const QString& userId, bool agree);

    void createGroupChatSession(const QString& loginSessionId, const QList<QString>& userIdList);

    void getMemberList(const QString& loginSessionId, const QString& chatSessionId);

    void searchUser(const QString& loginSessionId, const QString& key);

    void searchMessage(const QString& loginSessionId, const QString& chatSessionId, const QString& key);

    void searchMessageByTime(const QString& loginSessionId, const QString& chatSessionId, const QDateTime& beginTime, const QDateTime& endTime);

    void AccountLogin(const QString& username, const QString& password);

    void phoneLogin(const QString& phone, const QString& verifyCodeId, const QString& verifyCode);

    void userRegister(const QString& username, const QString& password, const QString &phone, const QString& verifyCodeId, const QString& verifyCode);

    void getSingleFile(const QString& loginSessionId, const QString& fileId);

    void speechConvertText(const QString& loginSessionId, const QString& fileId, const QByteArray& content);

private:
    QString makeRequestId();

    void sendAuthentication();

    QNetworkReply* sendHttpRequest(const QString& apiPath, const QByteArray& body);

    template<typename T>
    std::shared_ptr<T> httpResponseHandle(QNetworkReply* httpResp, bool* ok, QString* reason);

/* ===========================================
 *          websocket 接口声明
 * ========================================== */
public:
    void initWebsocket();

private:
    void WsResponseHandle(const im_proto::NotifyMessage& notifyMessage);

    void WsMessageHandle(const model::Message& message);

    void WsSessionCreateHandle(const model::ChatSessionInfo& chatSessionInfo);

    void WsRemoveFriendHandle(const QString& userId);

    void WsFriendAddApplyHandle(const model::UserInfo& userInfo);

    void WsFriendProcessHandle(const model::UserInfo& userInfo, bool agree);

    void receiveMessage(const QString& chatSessionId);

private:
    model::DataCenter* dataCenter;

    QNetworkAccessManager httpClient;   // http客户端

    QWebSocket websocketClient;         // websocket客户端

    QProtobufSerializer serializer;     // 序列化器

signals:
};


}

#endif // NETCLIENT_H
